/*
 * output.cpp
 *
 *  Created on: Jun 7, 2011
 *      Author: timothy
 */

#include "output.h"
#include "list.h"
#include "debug.h"
#include "shingletypes.h"

#include <string.h>

extern arg_vars *g_ArgVars;

		// METHODS //
void OutFile::Write()
{
	writeHeader();
	doneWithFile = 0;
	while(!In->EndOfFile() || edgeList)
		writeNextEntry();
	fprintf(stream, "]\n");
}
void OutFile::writeHeader()
{
	fprintf(stream, "graph [\n node_count %d\n edge_count %d\n\n node_data size float\n node_data community int\n node_data tag int\n\n", In->numVertices, In->numEdges);
}
void OutFile::writeNextEntry()
{
	if(!In->EndOfFile())
	{
		int vertex = readVertex();
		if(vertex != -1)
			vertexList.push_back(vertex);
	}
	else if(!doneWithFile)
	{
		list<int>::iterator vertex;
		for(vertex = vertexList.begin(); vertex != vertexList.end(); ++vertex)
		{
			Union->AddVertexToAudit(*vertex);
		}
		for(edge_t *audit = edgeList; audit != NULL; audit = audit->next)
		{
			Union->AddEdgeToAudit(audit->from, audit->to);
		}
		doneWithFile = 1;
	}
	else if (!vertexList.empty())
	{
		int vertex = vertexList.front();
		vertexList.pop_front();
		fprintf(stream, " node [\n   id %d\n   degree 1\n   size 2\n   community %d\n   tag %d \n]\n", vertex, Union->GetGroupID(vertex), vertex);
	}
	else if (edgeList)
	{
		edge *e = edgeList;
		edgeList = edgeList->next;
		fprintf(stream, " edge [\n   id %d\n   source %d\n   target %d\n ]\n", edgeCounter++, e->from, e->to);
		free(e);
	}
}
int OutFile::readVertex()
{
	if(!In->ReadLine(inBuff)) return -1;
	Vertex *ret = new Vertex(inBuff);
	if(!ret) return -1;
	NeighborListEntry *iter = ret->Neighbors->StartIterator();
	while(iter)
	{
		addEdge(ret->ID, iter->value);
		iter = iter->next;
	}
	int ID = ret->ID;
	delete(ret);
	return ID;
}
void OutFile::addEdge(int from, int to)
{
	if(from >= to) return; // Only add each edge once.

	edge_t *newEdge = (edge_t*)malloc(sizeof(edge_t));
	newEdge->from = from;
	newEdge->to = to;
	newEdge->next = 0;
	if(mostRecentEdge)
		mostRecentEdge->next = newEdge;
	else
		edgeList = newEdge;
	mostRecentEdge = newEdge;
}

OutFile::OutFile(InFile *in, UnionFindTree *uni)
{
	In = in;
	Union = uni;
	stream = fopen(g_ArgVars->outfile_n, "w");
	edgeList = NULL;
	mostRecentEdge = NULL;
	edgeCounter = 0;
	inBuff = (char*)malloc(In->lineLength);
}
OutFile::~OutFile()
{
	fclose(stream);
	free(inBuff);
}
